/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package xenon3d.vector;

/**
 * This class represents a vector in 3 dimensional floating point vector space.
 * @author Volker Everts
 * @version 0.1 - 19.08.2008: Created
 */
public class Vector2f extends Point2f {

    // <editor-fold defaultstate="collapsed" desc=" Static Attributes ">

    /** The serial version UID. */
    private static final long serialVersionUID = 20110917L;

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc=" Initialization ">

    /**
     * Creates a new Vector3f with the coordinates (0, 0).
     */
    public Vector2f() {
        super();
    }

    /**
     * Creates a new Vector2f using the specified coordinates.
     * @param x the x coordinate
     * @param y the y coordinate
     */
    public Vector2f(float x, float y) {
        super(x, y);
    }

    /**
     * Creates a new Vector2f with the same coordinates as the specified tuple,
     * point or vector.
     * @param t the other tuple, point or vector
     */
    public Vector2f(Tuple2f t) {
        super(t);
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc=" Public Methods ">

    /**
     * Inverts this vector in place. Alias method for negate().
     */
    public final void invert() {
        x = -x;
        y = -y;
    }

    /**
     * Sets the value of this vector to the inversion of the specified vector.
     * Alias method for negate(Vector2f).
     * @param v the other vector
     */
    public final void invert(Vector2f v) {
        x = -v.x;
        y = -v.y;
    }

    /**
     * Normalizes this vector in place.<p>
     * NOTE: a vector of zero length gets normalized to (0, 1).
     */
    public final void normalize() {
        float norm = lengthSq();
        if (FMath.isUnit(norm, FMath.EPS)) return;
        if (norm > FMath.EPS) {
            norm = FMath.sqrt(norm);
            x /= norm;
            y /= norm;
        }
        else set(0.0f, 1.0f);
    }

    /**
     * Sets the value of this vector to the normalization of the specified vector.
     * @param v the other vector
     */
    public final void normalize(Vector2f v) {
        set(v);
        normalize();
    }

    /**
     * Returns the length of this vector.
     * @return the length of this vector
     */
    public final float length() {
        return FMath.sqrt(x * x + y * y);
    }

    /**
     * Returns the squared length of this vector.
     * @return the squared length
     */
    public final float lengthSq() {
        return x * x + y * y;
    }

    /**
     * Returns the inner product of this vector and another vector or point,
     * given by its x,y coordinates.
     * @param x the other point's x coordinate
     * @param y the other point's y coordinate
     * @return the dot product
     */
    public final float dot(float x, float y) {
        return this.x * x + this.y * y;
    }

    /**
     * Returns the inner product of this vector and another vector or point.
     * @param p the other vector (or point)
     * @return the dot product
     */
    public final float dot(Point2f p) {
        return x * p.x + y * p.y;
    }

    /**
     * Returns the angle between this vector and another vector.
     * @param v the other vector
     * @return the angle in degrees
     */
    public final float angle(Vector2f v) {
        float cos = dot(v) / (FMath.sqrt(lengthSq() * v.lengthSq()));
        if (cos < -1.0f) cos = -1.0f;
        else if (cos > 1.0f) cos = 1.0f;
        return FMath.acos(cos);
    }

    /**
     * Rotates this vector anticlockwise around a center by the specified number
     * of degrees.
     * @param degrees the number of degrees to rotate by, anticlockwise
     * @param center the center of rotation, or null, to rotate around (0,0)
     */
    public void rotate(float degrees, Point2f center) {
        float cos = FMath.cos(degrees);
        float sin = FMath.sin(degrees);
        if (center != null) {
            x -= center.x;
            y -= center.y;
        }
        x = x * cos - y * sin;
        y = x * sin + y * cos;
        if (center != null) {
            x += center.x;
            y += center.y;
        }
    }

    // </editor-fold>

} // end class Vector2f